#ifndef POINT_H
#define POINT_H

namespace MathGraphics
{
	struct Point
	{
		double x;
		double y;
		double z;

		Point(double xc, double yc, double zc);

		inline Point  operator +(const Point& v) const;
		inline Point  operator +(const Vector& v) const;
		inline Vector operator -(const Point& v) const;
		inline Point  operator -(const Vector& v) const;
		inline Point  operator *(double factor) const;
		inline Point  operator /(double factor) const;
		inline Point& operator +=(const Point& v);
		inline Point& operator *=(double factor);
		inline Point& operator /=(double factor);
	};

	inline Point operator *(double factor, const Point& v);

	bool operator==(const Point& p1, const Point& p2);
	bool operator!=(const Point& p1, const Point& p2);

	inline Point::Point(double xc = 0.0f, double yc = 0.0f, double zc = 0.0f) : x(xc), y(yc), z(zc) {}

	inline Point Point::operator +(const Point& v) const
	{
		return Point(this->x + v.x, this->y + v.y, this->z + v.z);
	}

	inline Point Point::operator +(const Vector& v) const
	{
		return Point(this->x + v.x, this->y + v.y, this->z + v.z);
	}

	inline Vector Point::operator -(const Point& v) const
	{
		return Vector(this->x - v.x, this->y - v.y, this->z - v.z);
	}

	inline Point Point::operator -(const Vector& v) const
	{
		return Point(this->x - v.x, this->y - v.y, this->z - v.z);
	}

	
	inline Point Point::operator *(double factor) const
	{
		return Point(factor * x, factor * y, factor * z);
	}

	inline Point Point::operator /(double factor) const
	{
		double invf = 1.0f / factor;

		return Point(this->x * invf, this->y * invf, this->z * invf);
	}

	inline Point& Point::operator +=(const Point& v) 
	{
		this->x += v.x;
		this->y += v.y;
		this->z += v.z;

		return *this;
	}

	inline Point& Point::operator *=(double factor)
	{
		x *= factor;
		y *= factor;
		z *= factor;

		return (*this);
	}

	inline Point& Point::operator /=(double factor)
	{
		double invf = 1.0f / factor;

		this->x *= invf;
		this->y *= invf;
		this->z *= invf;

		return *this;
	}

	inline Point operator *(double factor, const Point& v)
	{
		return Point(factor * v.x, factor * v.y, factor * v.z);
	}

	inline bool operator==(const Point& p1, const Point& p2)
	{
		if (p1.x == p2.x && p1.y == p2.y && p1.z == p2.z)
			return true;

		return false;
	}

	inline bool operator!=(const Point& p1, const Point& p2)
	{
		if (p1.x == p2.x && p1.y == p2.y && p1.z == p2.z)
			return false;

		return true;
	}
}

#endif